package com.hlj.ncp.system.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hlj.ncp.common.core.domain.AjaxResult;
import com.hlj.ncp.system.entity.SysMenu;
import com.hlj.ncp.system.mapper.SysMenuMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 菜单信息
 */
@Controller
@RequestMapping("/system/menu")
public class MenuController {
    
    @Autowired
    private SysMenuMapper menuMapper;
    
    /**
     * 菜单管理页面
     */
    @GetMapping({"", "/", "/index"})
    public String index() {
        return "system/menu/index";
    }
    
    /**
     * 获取菜单列表
     */
    @GetMapping("/list")
    @ResponseBody
    @Cacheable(value = "menuList", key = "#menuName + '-' + #status", unless = "#result.get('code') != 200")
    @Transactional(readOnly = true)
    public AjaxResult list(String menuName, String status) {
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(menuName)) {
            queryWrapper.like(SysMenu::getMenuName, menuName);
        }
        if (StringUtils.hasText(status)) {
            queryWrapper.eq(SysMenu::getStatus, status);
        }
        // 排序
        queryWrapper.orderByAsc(SysMenu::getParentId, SysMenu::getOrderNum);
        
        List<SysMenu> menus = menuMapper.selectList(queryWrapper);
        return AjaxResult.success(buildMenuTree(menus));
    }
    
    /**
     * 获取菜单下拉树列表
     */
    @GetMapping("/treeselect")
    @ResponseBody
    public AjaxResult treeselect() {
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMenu::getStatus, "0"); // 只查询正常状态的菜单
        queryWrapper.orderByAsc(SysMenu::getParentId, SysMenu::getOrderNum);
        List<SysMenu> menus = menuMapper.selectList(queryWrapper);
        return AjaxResult.success(buildMenuTree(menus));
    }
    
    /**
     * 获取菜单详细信息
     */
    @GetMapping("/{menuId}")
    @ResponseBody
    public AjaxResult getInfo(@PathVariable Long menuId) {
        return AjaxResult.success(menuMapper.selectById(menuId));
    }
    
    /**
     * 新增菜单
     */
    @PostMapping("/add")
    @ResponseBody
    @CacheEvict(value = "menuList", allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult add(@RequestBody SysMenu menu) {
        // 验证菜单名称是否唯一
        if (checkMenuNameUnique(menu) != 0) {
            return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败，菜单名称已存在");
        }
        
        // 设置默认值
        menu.setCreateTime(LocalDateTime.now());
        menu.setCreateBy(getCurrentUsername());
        
        // 插入数据
        int rows = menuMapper.insert(menu);
        return rows > 0 ? AjaxResult.success() : AjaxResult.error("新增菜单失败");
    }
    
    /**
     * 修改菜单
     */
    @PostMapping("/update")
    @ResponseBody
    @CacheEvict(value = "menuList", allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult update(@RequestBody SysMenu menu) {
        // 验证菜单是否存在
        SysMenu existMenu = menuMapper.selectById(menu.getMenuId());
        if (existMenu == null) {
            return AjaxResult.error("菜单不存在");
        }
        
        // 验证菜单名称是否唯一
        if (!existMenu.getMenuName().equals(menu.getMenuName()) && checkMenuNameUnique(menu) != 0) {
            return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败，菜单名称已存在");
        }
        
        // 不能选择自己作为父菜单
        if (menu.getMenuId().equals(menu.getParentId())) {
            return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败，上级菜单不能选择自己");
        }
        
        // 设置更新信息
        menu.setUpdateTime(LocalDateTime.now());
        menu.setUpdateBy(getCurrentUsername());
        
        // 更新数据
        int rows = menuMapper.updateById(menu);
        return rows > 0 ? AjaxResult.success() : AjaxResult.error("修改菜单失败");
    }
    
    /**
     * 删除菜单
     */
    @PostMapping("/delete/{menuId}")
    @ResponseBody
    @CacheEvict(value = "menuList", allEntries = true)
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult delete(@PathVariable Long menuId) {
        // 判断是否存在子菜单
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMenu::getParentId, menuId);
        int count = menuMapper.selectCount(queryWrapper).intValue();
        if (count > 0) {
            return AjaxResult.error("存在子菜单,不允许删除");
        }
        
        // 删除菜单
        int rows = menuMapper.deleteById(menuId);
        return rows > 0 ? AjaxResult.success() : AjaxResult.error("删除菜单失败");
    }
    
    /**
     * 构建菜单树
     */
    private List<SysMenu> buildMenuTree(List<SysMenu> menus) {
        // 先将菜单列表转换为Map，方便查找
        Map<Long, SysMenu> menuMap = menus.stream().collect(Collectors.toMap(SysMenu::getMenuId, menu -> menu));
        
        // 构建树形结构
        List<SysMenu> result = new ArrayList<>();
        for (SysMenu menu : menus) {
            // 如果是根菜单，直接添加到结果列表
            if (menu.getParentId() == 0L || !menuMap.containsKey(menu.getParentId())) {
                result.add(menu);
                continue;
            }
            
            // 如果不是根菜单，将其添加到父菜单的子菜单列表中
            SysMenu parent = menuMap.get(menu.getParentId());
            parent.getChildren().add(menu);
        }
        
        return result;
    }
    
    /**
     * 检查菜单名称是否唯一
     */
    private int checkMenuNameUnique(SysMenu menu) {
        Long menuId = menu.getMenuId() == null ? -1L : menu.getMenuId();
        Long parentId = menu.getParentId() == null ? 0L : menu.getParentId();
        
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMenu::getParentId, parentId);
        queryWrapper.eq(SysMenu::getMenuName, menu.getMenuName());
        queryWrapper.ne(menuId > 0, SysMenu::getMenuId, menuId);
        
        return menuMapper.selectCount(queryWrapper).intValue();
    }
    
    /**
     * 获取当前登录用户名
     */
    private String getCurrentUsername() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authentication.getName();
    }
} 